package com.atguigu.guigu.common.handler;

import com.atguigu.guigu.common.exception.BusinessException;
import com.atguigu.guigu.common.result.R;
import com.atguigu.guigu.common.result.ResultCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

//@ControllerAdvice 当前类为所有的Controller的异常处理类
// 但是当前类处理完异常后返回的结果 需要转发或重定向
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /*
        每个具体的异常如果我们希望返回自定义的R对象，都需要写一个异常处理器

        我们希望以后抛出的所有异常都能被一个异常处理器处理
        同时在异常处理的业务代码中可以判断应该如何返回一个R对象(给他设置合适的code和message)

        解决：
            - 在可能出现异常的代码中 手动try catch抛出
              自定义类型的异常(将所有的将来出现的异常都转为同一个类型的异常)
            - 自定义类型的异常类 还需要扩展(携带异常处理器需要返回的R对象需要的 code和message属性值)


     */
    //1、处理Exception异常的处理器
    @ExceptionHandler(value = Exception.class)
    //e代表controller中出现的异常
    public R exception(Exception e){ //一般和@ExceptionHandlervalue指定的异常类型一样
        log.error(ExceptionUtils.getStackTrace(e));
        return R.error();
    }
    //3、处理自定义类型异常的处理器
    @ExceptionHandler(value = BusinessException.class)
    public R exception(BusinessException e){
        log.error(ExceptionUtils.getStackTrace(e));
        return R.error().code(e.getCode()).message(e.getMessage());
    }
    //2、处理指定类型异常的处理器
    @ExceptionHandler(value = BadSqlGrammarException.class)
    public R exception(BadSqlGrammarException e){
        log.error(ExceptionUtils.getStackTrace(e));
        return R.setResult(ResultCodeEnum.BAD_SQL_GRAMMAR_ERROR);
    }
    @ExceptionHandler(value = ArithmeticException.class)
    public R exception(ArithmeticException e){
        log.error(ExceptionUtils.getStackTrace(e));
        return R.setResult(ResultCodeEnum.SERVLET_ERROR);
    }

}
